#include "manifest.h"

static mapsl_t stamps;

static mapsl_t map() {
    if (stamps == null) {
        stamps = mapsl_create(100);
    }
    return stamps;
}

static void traceHumanReadable(const char* file, int line, const char *func, const char* label, int64 delta) {
    if (delta < 10LL * 1000) {
        trace0(file, line, func, "time: \"%s\" %lld nanoseconds\n", label, delta);
    } else if (delta < 10LL * 1000 * 1000) {
        trace0(file, line, func, "time: \"%s\" %lld microseconds\n", label, delta / 1000LL);
    } else if (delta < 10LL * 1000 * 1000 * 1000) {
        trace0(file, line, func, "time: \"%s\" %lld milliseconds\n", label, delta / (1000LL * 1000));
    } else {
        trace0(file, line, func, "time: \"%s\" %lld seconds\n", label, delta / (1000LL * 1000 * 1000));
    }
}

static int64 self_time; /* = 0 */
static bool trace_timestamp; /* = false */

int64 timestamp0(const char* file, int line, const char *func, const char* label) {
    /* returns 0 on the first use and delta in nanoseconds on second call */
    if (self_time == 0) {
        self_time = 1;
        timestamp("timestamp-self-delta");
        self_time = timestamp("timestamp-self-delta");
        if (self_time <= 0) {
            self_time = 1;
        }
        trace_timestamp = true;
    }
    void* m = map();
    int64 t = cputime();
    int64 s = mapsl_remove(m, label);
    if (s == 0) {
        mapsl_put(m, label, t);
        return 0;
    } else {
        int64 delta = t - s - self_time;
        delta = delta < 1 ? 1 : delta;
        if (trace_timestamp) {
            traceHumanReadable(file, line, func, label, delta);
        }
        return delta;
    }
}
